package com.klm.easymq.example;

import com.klm.easymq.annotation.Idempotent;
import com.klm.easymq.annotation.MQListener;
import com.klm.easymq.annotation.MQProducer;
import com.klm.easymq.annotation.Retry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 消息处理示例类
 * 演示如何使用Easy-MQ的核心注解功能
 */
@Slf4j
@Component
public class MessageExample {
    
    /**
     * 消息生产者示例
     * 使用@MQProducer注解自动发送消息
     */
    @MQProducer(
        topic = "order.created",
        tag = "create",
        key = "#order.orderId",
        sendMode = MQProducer.SendMode.SYNC
    )
    public OrderMessage createOrder(OrderRequest request) {
        // 业务逻辑：创建订单
        OrderMessage order = new OrderMessage();
        order.setOrderId(request.getOrderId());
        order.setUserId(request.getUserId());
        order.setAmount(request.getAmount());
        order.setStatus("CREATED");
        
        log.info("订单创建成功: orderId={}, userId={}, amount={}", 
                order.getOrderId(), order.getUserId(), order.getAmount());
        
        // 返回的消息会自动发送到MQ
        return order;
    }
    
    /**
     * 消息消费者示例
     * 使用@MQListener注解自动消费消息
     */
    @MQListener(
        topic = "order.created",
        group = "inventory-service",
        idempotentKey = "#order.orderId",
        retryPolicy = @Retry(
            maxAttempts = 3,
            interval = 1000,
            backoffPolicy = Retry.BackoffPolicy.EXPONENTIAL,
            multiplier = 2.0,
            maxInterval = 10000
        ),
        concurrency = 2,
        ackMode = MQListener.AckMode.AUTO
    )
    public void handleOrderCreated(OrderMessage order) {
        log.info("收到订单创建消息: orderId={}, userId={}, amount={}", 
                order.getOrderId(), order.getUserId(), order.getAmount());
        
        // 业务逻辑：处理订单创建
        // 例如：更新库存、发送通知等
        
        // 模拟业务处理
        try {
            Thread.sleep(100);
            log.info("订单处理完成: orderId={}", order.getOrderId());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("订单处理被中断", e);
        }
    }
    
    /**
     * 幂等控制示例
     * 使用@Idempotent注解防止重复处理
     */
    @Idempotent(
        key = "#request.requestId",
        expireSeconds = 3600,
        strategy = Idempotent.Strategy.THROW_EXCEPTION,
        errorMessage = "请求已处理，请勿重复提交"
    )
    public Map<String, Object> processRequest(ProcessRequest request) {
        log.info("处理请求: requestId={}, data={}", request.getRequestId(), request.getData());
        
        // 业务逻辑处理
        Map<String, Object> result = Map.of(
            "requestId", request.getRequestId(),
            "status", "SUCCESS",
            "timestamp", System.currentTimeMillis()
        );
        
        log.info("请求处理完成: requestId={}", request.getRequestId());
        return result;
    }
    
    /**
     * 延迟消息生产者示例
     */
    @MQProducer(
        topic = "order.timeout",
        tag = "timeout",
        key = "#order.orderId",
        delayLevel = 3, // 10秒延迟
        messageType = MQProducer.MessageType.NORMAL,
        sendMode = MQProducer.SendMode.ASYNC
    )
    public OrderMessage scheduleOrderTimeout(OrderMessage order) {
        log.info("调度订单超时检查: orderId={}", order.getOrderId());
        return order;
    }
    
    /**
     * 顺序消息消费者示例
     */
    @MQListener(
        topic = "order.status.update",
        group = "order-service",
        idempotentKey = "#order.orderId",
        retryPolicy = @Retry(maxAttempts = 2),
        concurrency = 1, // 顺序消息必须单线程
        ackMode = MQListener.AckMode.MANUAL
    )
    public void handleOrderStatusUpdate(OrderMessage order) {
        log.info("处理订单状态更新: orderId={}, status={}", 
                order.getOrderId(), order.getStatus());
        
        // 业务逻辑：更新订单状态
        // 顺序消息确保同一订单的状态更新按顺序处理
    }
    
    // 内部类定义
    public static class OrderRequest {
        private String orderId;
        private String userId;
        private double amount;
        
        // getters and setters
        public String getOrderId() { return orderId; }
        public void setOrderId(String orderId) { this.orderId = orderId; }
        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }
        public double getAmount() { return amount; }
        public void setAmount(double amount) { this.amount = amount; }
    }
    
    public static class OrderMessage {
        private String orderId;
        private String userId;
        private double amount;
        private String status;
        
        // getters and setters
        public String getOrderId() { return orderId; }
        public void setOrderId(String orderId) { this.orderId = orderId; }
        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }
        public double getAmount() { return amount; }
        public void setAmount(double amount) { this.amount = amount; }
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
    }
    
    public static class ProcessRequest {
        private String requestId;
        private String data;
        
        // getters and setters
        public String getRequestId() { return requestId; }
        public void setRequestId(String requestId) { this.requestId = requestId; }
        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
    }
} 